﻿
#region using

using System;
using System.Web;
using System.Web.UI;
using System.Net;
using System.Xml;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.Generic;
using BlogEngine.Core;

#endregion

namespace Controls
{
    public class Twitter : Control
    {
        private string _username;
        private string _password;
        private Timeline _timeline;
        private int _statuses;

        static Twitter() { }

        #region Properties

        /// <summary>
        /// Username of your Twitter account
        /// </summary>
        public string Username
        {
            get { return _username; }
            set { _username = value; }
        }
        /// <summary>
        /// Password of your Twitter account
        /// </summary>
        public string Password
        {
            get { return _password; }
            set { _password = value; }
        }
        /// <summary>
        /// Type of timeline to get from Twitter
        /// </summary>
        public Timeline Timeline
        {
            get { return _timeline; }
            set { _timeline = value; }
        }
        /// <summary>
        /// Number Of Statuses to render in the control (maximum 20 recommended)
        /// </summary>
        public int NumberOfStatuses
        {
            get { return _statuses; }
            set { _statuses = value; }
        }
        
        #endregion

        public override void RenderControl(HtmlTextWriter writer)
        {
            try
            {
                if (_username == null || _password == null)
                    writer.Write("Username or password is missing.");
                else
                    writer.Write(GetTimeLine());
            }
            catch (Exception ex)
            {
                writer.Write(ex.Message);
            }
        }

        /// <summary>
        /// Returns formatted timeline
        /// </summary>
        private string GetTimeLine()
        {
            try
            {
                // Select timeline url
                string timelineUrl = null;
                switch (_timeline)
                {
                    case Timeline.Public:
                        timelineUrl = @"http://twitter.com/statuses/public_timeline.xml";
                        break;
                    case Timeline.Friends:
                        timelineUrl = @"http://twitter.com/statuses/friends_timeline.xml";
                        break;
                    case Timeline.User:
                        timelineUrl = @"http://twitter.com/statuses/user_timeline.xml";
                        break;
                    default:
                        timelineUrl = @"http://twitter.com/statuses/user_timeline.xml";
                        break;
                }

                // Get timeline from Twitter
                WebRequest request = WebRequest.Create(timelineUrl);
                WebResponse response = null;
                StreamReader reader = null;
                XmlDocument document = new XmlDocument();
                request.Headers.Add(HttpRequestHeader.Authorization, "Basic " + GetCredentials());
                request.Method = "GET";
                response = request.GetResponse();
                reader = new StreamReader(response.GetResponseStream());
                document.LoadXml(reader.ReadToEnd());
                reader.Close();
                response.Close();

                // Build twitter updates from XML stream
                StringBuilder sb = new StringBuilder();
                sb.Append("<ul class=\"twitter\" id=\"twitter\">");

                XmlNodeList statusesList = document.GetElementsByTagName("status");
                string link = "<a href=\"{0}\">{1}</a>";
                if (_statuses == 0)
                    _statuses = statusesList.Count;

                for (int i = 0; i < _statuses; i++)
                {
                    XmlNode status = statusesList[i];

                    sb.Append("<li>");

                    // Display of the sender in case of public or friend timeline
                    if (_timeline != Timeline.User)
                    {
                        sb.AppendFormat(link, @"http://www.twitter.com/" + status["user"]["screen_name"].InnerText, status["user"]["screen_name"].InnerText);
                        sb.Append(" " + Resources.labels.wrote + " ");
                    }

                    string innerText = status["text"].InnerText;

                    // Conversion of url in link
                    Regex regex = new Regex(@"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?");
                    MatchCollection matches = regex.Matches(innerText);
                    foreach (Match match in matches)
                    {
                        innerText = innerText.Replace(match.Value, string.Format(link, match.Value, match.Value));
                    }

                    // Conversion of twitter user in link
                    if (innerText.StartsWith("@"))
                    {
                        int pos = innerText.IndexOf(' ');
                        string reply = innerText.Substring(1, pos - 1);
                        sb.AppendFormat(innerText.Replace(reply, link), @"http://www.twitter.com/" + reply, reply);             
                    }
                    else
                        sb.Append(innerText);

                    sb.Append("</li>");
                }

                sb.Append("</ul>");

                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Returns encoded credentials
        /// </summary>
        private string GetCredentials()
        {
            string data = _username +  ":" + _password;
            byte[] bytes = new byte[data.Length];
            bytes = System.Text.Encoding.UTF8.GetBytes(data);
            string encodedData = Convert.ToBase64String(bytes);
            return encodedData;
        }

    }
}

public enum Timeline
{
    User,
    Friends,
    Public
}